package com.example.file.utils;

import com.example.file.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.Loader;

import java.io.*;
import java.util.concurrent.TimeUnit;

@Slf4j
public class FfmpegUtils {

    /**
     * 拷贝视频
     *
     * @param videoPath 视频路径
     * @param timeout   等待的最长时间
     * @param unit      参数的时间 timeout 单位
     * @return 是否成功拷贝
     */
    public static byte[] ffmpegCopyVideo(String videoPath, long timeout, TimeUnit unit) {

        if (timeout <= 0) {
            throw new IllegalArgumentException("timeout不能小于等于0");
        }


        if (unit == null) {
            unit = TimeUnit.MINUTES;
        }

        File videoFile = new File(videoPath);
        validIsFile(videoFile);
        ProcessBuilder extractBuilder = new ProcessBuilder(
                ffmpeg(),
                "-i", videoPath,
                "-c", "copy",  // 使用-c copy直接拷贝视频流
                "-movflags", "frag_keyframe+empty_moov",  // 使 MP4 支持流式传输
                "-f", "mp4",             // 输出 MP4 格式
                "-"//输出到控制台
        );

        try {

            StringBuilder sb = new StringBuilder();
            Process process = extractBuilder.start();

            try (InputStream inputStream = process.getInputStream()) {

                processErrorMsg(process, sb);
                byte[] bytes = inputStream.readAllBytes();
                boolean result = process.waitFor(timeout, unit);
                if (!result) {
                    throw new ServiceException("子进程退出之前已超过等待时间");
                }

                log.info("拷贝视频:{}", sb);
                return bytes;
            }

        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }


    }

    private static void processErrorMsg(Process process, StringBuilder stringBuilder) {

        new Thread(() -> {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line);
                }
            } catch (IOException e) {
                log.error("打印命令行错误日志出现异常  errMsg:{}", e.getMessage(), e);
            }
        }).start();
    }

    public static void validIsFile(File file) {
        validExists(file);
        if (!file.isFile()) {
            throw new IllegalArgumentException("不是文件");
        }
    }

    public static void validExists(File file) {
        if (!file.exists()) {
            throw new IllegalArgumentException("文件不存在");
        }
    }

    static class LazyFfmpeg {
        private static final String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
    }

    public static String ffmpeg() {
        return LazyFfmpeg.ffmpeg;
    }
}
